package controller

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"mini-app/config"
	"mini-app/config/mysql"
	"mini-app/config/redis"
	"mini-app/internal/app/grpc/client"
	"mini-app/internal/app/grpc/protoc/sale_adminc"
	"mini-app/internal/app/grpc/protoc/system_admin"
	"mini-app/internal/app/web/service"
	"mini-app/internal/dal"
	"mini-app/internal/define"
	"mini-app/internal/pkg"
	"net/http"
	"path"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	wechatv3 "github.com/go-pay/gopay/wechat/v3"
	"github.com/shopspring/decimal"
)

const (
	FILE_CONTINUE = 1
	FILE_END      = 2
)

type Index struct{}

func (Index) ExpressFee(c *gin.Context) {
	saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
	if saleAdminClientErr != nil {
		logx.Error(c.Request.Context(), "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
		return
	}
	rsp, getExpressFeeErr := saleAdminClient.ExpressFee(c.Request.Context(), &sale_adminc.ExpressFeeReq{GoodsId: "1"})
	if getExpressFeeErr != nil {
		return
	}
	fmt.Println(rsp)
}

func (Index) GetQrCode(c *gin.Context) {
	var params struct {
		Page      string `json:"page"`
		Scene     string `json:"scene"`
		Env       string `json:"env"`
		IsHyaline bool   `json:"is_hyaline"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	data, err := pkg.MiniProgram{}.GetUnlimitedQRCode(c.Request.Context(), params.Page, params.Scene, params.Env, params.IsHyaline)
	response.JSON(c, data, err)
}

// FileUpload 文件上传
// file 文件
// dir 保存路径
func (Index) FileUpload(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		response.JSON(c, "", errorx.New("未获取到上传的文件", -1))
		return
	}
	logx.Info(context.Background(), "file", logx.Any("file", file.Filename))
	f, _ := file.Open()
	fmt.Println(file.Size) //50671
	AllBytes, _ := io.ReadAll(f)

	ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
	defer cancel()
	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		logx.Error(c.Request.Context(), "user login system admin error", logx.Any("err", clientErr.Error()))
		response.JSON(c, nil, errorx.New("图片上传失败", -1))
		return
	}
	fileName := helper.RandString(8) + path.Ext(file.Filename)
	req := system_admin.FileUploadReq{
		FileName:   fileName,
		Dir:        c.PostForm("dir"),
		SystemName: "mini-app",
	}
	fileClient, fileClientErr := SystemAdminClient.FileUpload(context.Background())
	if fileClientErr != nil {
		logx.Error(c.Request.Context(), "file upload error", logx.Any("err", fileClientErr.Error()))
		return
	}

	var status = 0
	reader := bytes.NewReader(AllBytes)
	var totalSize = file.Size
	for {
		var buffSize int
		if totalSize >= 3*1024*1024 {
			buffSize = 3 * 1024 * 1024
		} else {
			buffSize = int(totalSize)
		}
		var buffer = make([]byte, buffSize) // 3M
		_, err := reader.Read(buffer)
		totalSize -= int64(buffSize)
		if err != nil {
			if err == io.EOF { //文件读取完毕，改变status
				status = FILE_END
			} else {
				panic(err)
			}
		} else {
			if buffSize < 3*1024*1024 || totalSize == 0 {
				status = FILE_END
			} else {
				status = FILE_CONTINUE
			}
		}
		if status == FILE_CONTINUE {
			req.File = buffer
			err = fileClient.Send(&req)
			if err != nil && err != io.EOF {
				response.JSON(c, nil, err)
				return
			}
			fmt.Println("continue")
		} else if status == FILE_END {
			req.File = buffer
			req.End = 1
			err = fileClient.Send(&req)
			if err != nil && err != io.EOF {
				response.JSON(c, nil, err)
				return
			}
			fmt.Println("end")
			break
		}
	}

	for {
		select {
		case <-fileClient.Context().Done():
			fmt.Println("context done")
			return
		case <-ctx.Done():
			fmt.Println("time time out ---")
			return
		default:
			msg, err := fileClient.Recv()
			// 消息处理
			if err == nil && msg != nil {
				response.JSON(c, gin.H{
					"file_url": msg.FileUrl,
				}, errorx.New(msg.Msg, int(msg.Code)))
				return
			} else {
				if err != io.EOF {
					logx.Error(c.Request.Context(), "file upload get error msg", logx.Any("err", err), logx.Any("msg", msg))
					response.JSON(c, nil, err)
					return
				}
			}
		}
	}
}

// 判断万象是否登录
func (Index) WanxiangLogin(c *gin.Context) {
	token := c.GetString("token")
	rdb := redis.NewDB()
	openid, err := rdb.Get(c.Request.Context(), define.MiniAppSessionOpenid+token).Result()
	if err != nil || openid == "" {
		response.JSON(c, false, errorx.New("万象未登录", -1))
		return
	}
	accessSession, err := rdb.Get(c.Request.Context(), define.WanxiangPointsAccessToken+openid).Result()
	response.JSON(c, accessSession != "", err)
}

// 第三方授权回调
func (Index) OauthCallback(c *gin.Context) {
	token := c.GetString("token")
	code := c.Query("code")
	webServerRedirectUri := c.Query("webServerRedirectUri")
	err := service.Auth{}.OauthCallback(c.Request.Context(), token, code, webServerRedirectUri)
	response.JSON(c, nil, err)
}

// 微信支付回调
func (Index) WechatV3Notify(c *gin.Context) {
	pkg.WechatPay{}.V3ConfigInit("", "", "")
	resource, err := wechatv3.V3ParseNotify(c.Request)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			// 错误码，SUCCESS为清算机构接收成功，其他错误码为失败。
			"code": "SUCCESS",
			"msg":  "failed to parse request body",
		})
		return
	}
	result, err := resource.DecryptPayCipherText(config.Config.WechatV3Config.APIv3Key)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			// 错误码，SUCCESS为清算机构接收成功，其他错误码为失败。
			"code": "SUCCESS",
			"msg":  "failed to parse request body",
		})
		return
	}
	logx.Info(context.Background(), "WechatV3Notify", logx.Any("result", result))
	// 处理订单状态为已支付
	if result.TradeState == "SUCCESS" {
		query := dal.Use(mysql.NewDB())
		o := query.Order
		tx := o.WithContext(context.Background()).
			Where(o.BatchID.Eq(result.OutTradeNo)).
			Where(o.Openid.Eq(result.Payer.Openid)).
			Where(o.OrderStatus.In(define.OrderStatusUnpaid, define.OrderStatusUnPaidExpreeFee))
		orderInfo, _ := tx.Take()
		if orderInfo == nil {
			logx.Error(context.Background(), "WechatV3Notify: 不存在的订单或订单已支付")
			c.XML(http.StatusOK, gin.H{
				"msg": "不存在的订单或订单已支付",
			})
		}

		// 获取零售grpc客户端
		saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
		if saleAdminClientErr != nil {
			c.Abort()
			return
		}

		if orderInfo != nil && orderInfo.ID != "" {
			goodsInfo, _ := saleAdminClient.GoodsDetail(c.Request.Context(), &sale_adminc.GoodsDetailReq{
				GoodsId: orderInfo.GoodsID,
			})

			if goodsInfo == nil {
				err = errorx.New("未找到商品信息", -1)
				logx.Error(context.Background(), "WechatV3Notify: 未找到商品信息")
				c.Abort()
				return
			}

			if goodsInfo.GoodsType == define.GoodsTypeGuide && goodsInfo.GoodsPrice > 0 {
				// 2025-10-16 有价格的导流商品，需要支付和兑换码两个环节
				_, err = tx.UpdateColumnSimple(o.OrderStatus.Value(define.OrderStatusPainAndToRedeem))
				if err != nil {
					logx.Error(context.Background(), "WechatV3Notify: 更新订单状态失败", logx.Err(err))
					c.Abort()
				}
			} else if orderInfo.PurchaseMethod == 1 { // 站点自提
				tx.UpdateColumnSimple(o.OrderStatus.Value(define.OrderStatusToPickUp))

				err = service.Order{}.UploadShippingInfo(result.Payer.Openid, result.OutTradeNo)

				logx.Info(context.Background(), "wechat_v3_notify", logx.Any("upload_shipping_info", err))
			} else if orderInfo.PurchaseMethod == 2 { // 快递到家
				tx.UpdateColumnSimple(o.OrderStatus.Value(define.OrderStatusToDelivery))
			}
		}
		// 支付成功后，同步到零售后台

		// 活动订单
		if orderInfo.OnlineEventID != "" {
			saleAdminClient.CreateOnlineOrder(c.Request.Context(), &sale_adminc.CreateOnlineOrderReq{
				OutTradeNo: orderInfo.BatchID,
				List: []*sale_adminc.CreateOnlineOrderReq_List{
					{
						ChildOutTradeNo: orderInfo.ID,
						GoodsId:         orderInfo.GoodsID,
						Univalent:       orderInfo.Univalent,
						Count:           int32(orderInfo.Count),
					},
				},
				UserAddress: &sale_adminc.UserAddress{
					UserName:      orderInfo.UserName,
					TelNumber:     orderInfo.TelNumber,
					PostalCode:    orderInfo.PostalCode,
					ProvinceName:  orderInfo.ProvinceName,
					CityName:      orderInfo.CityName,
					CountyName:    orderInfo.CountyName,
					StreetName:    orderInfo.StreetName,
					DetailAddress: orderInfo.DetailAddress,
				},
				ExpressFee: orderInfo.ExpressFee,
			})
			// 快递订单
		} else if orderInfo.PurchaseMethod == 2 {
			saleAdminClient.CreateOnlineOrder(c.Request.Context(), &sale_adminc.CreateOnlineOrderReq{
				OutTradeNo: orderInfo.BatchID,
				List: []*sale_adminc.CreateOnlineOrderReq_List{
					{
						ChildOutTradeNo: orderInfo.ID,
						GoodsId:         orderInfo.GoodsID,
						Univalent:       orderInfo.Univalent,
						Count:           int32(orderInfo.Count),
						RobotID:         orderInfo.RobotID,
					},
				},
				UserAddress: &sale_adminc.UserAddress{
					UserName:      orderInfo.UserName,
					TelNumber:     orderInfo.TelNumber,
					PostalCode:    orderInfo.PostalCode,
					ProvinceName:  orderInfo.ProvinceName,
					CityName:      orderInfo.CityName,
					CountyName:    orderInfo.CountyName,
					StreetName:    orderInfo.StreetName,
					DetailAddress: orderInfo.DetailAddress,
				},
				ExpressFee: orderInfo.ExpressFee,
			})
		} else if orderInfo.PurchaseMethod == 1 { // 自提订单
			// 零售平台创单,拿到取货码
			pickupDeadline := time.Now().Unix() + 60*60*1 // 取货截止时间,1小时后失效
			req := sale_adminc.CreateOrderReq{}
			req.RemoteIp = ""
			req.List = append(req.List, &sale_adminc.CreateOrderReq_List{
				OutTradeNo:      orderInfo.BatchID,
				ChildOutTradeNo: orderInfo.ID,
				RobotId:         orderInfo.RobotID,
				GoodsId:         orderInfo.GoodsID,
				GoodsName:       orderInfo.GoodsName,
				Count:           int32(orderInfo.Count),
				Univalent:       decimal.NewFromFloat(orderInfo.Univalent).Mul(decimal.NewFromInt(100)).IntPart(),
				ExpiredAt:       pickupDeadline,
			})

			req.OrderStatus = define.OrderStatusPainAndToRedeem
			orderRsp, orderErr := saleAdminClient.CreateOrder(c.Request.Context(), &req)
			if orderErr != nil {
				logx.Error(c.Request.Context(), "create order error", logx.Any("orderRsp", orderRsp), logx.Any("orderErr", orderErr))
				return
			}
			if orderRsp.Code != 0 {
				err = errorx.New(orderRsp.Msg, int(orderRsp.Code))
				return
			}
			//saleAdminClient.CreateOnlineOrder(c.Request.Context(), &sale_adminc.CreateOnlineOrderReq{
			//	OutTradeNo: orderInfo.BatchID,
			//	List: []*sale_adminc.CreateOnlineOrderReq_List{
			//		{
			//			ChildOutTradeNo: orderInfo.ID,
			//			GoodsId:         orderInfo.GoodsID,
			//			Univalent:       orderInfo.Univalent,
			//			Count:           int32(orderInfo.Count),
			//			RobotID:         orderInfo.RobotID,
			//		},
			//	},
			//	UserAddress: &sale_adminc.UserAddress{
			//		UserName:      orderInfo.UserName,
			//		TelNumber:     orderInfo.TelNumber,
			//		PostalCode:    orderInfo.PostalCode,
			//		ProvinceName:  orderInfo.ProvinceName,
			//		CityName:      orderInfo.CityName,
			//		CountyName:    orderInfo.CountyName,
			//		StreetName:    orderInfo.StreetName,
			//		DetailAddress: orderInfo.DetailAddress,
			//	},
			//	ExpressFee: orderInfo.ExpressFee,
			//})
		}
	}

	// 返回处理结果
	c.XML(http.StatusOK, nil)
}
